package org.popupcommunication.controller;

import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.popupcommunication.exceptions.SujetNotFoundException;
import org.popupcommunication.model.Group;
import org.popupcommunication.model.ResponseForum;
import org.popupcommunication.model.SujetForum;
import org.popupcommunication.model.User;
import org.popupcommunication.service.GroupManager;
import org.popupcommunication.service.ResponseForumManager;
import org.popupcommunication.service.SujetForumManager;
import org.popupcommunication.service.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("forum")
public class ForumController {
	@Autowired
	UserManager userService;
	@Autowired
	GroupManager groupService;
	@Autowired
	SujetForumManager sujetForumService;
	@Autowired
	ResponseForumManager reponseForumService;

	@RequestMapping(value = "", method = RequestMethod.GET)
	public String viewListForum(HttpSession session, Model model) throws UnsupportedEncodingException {
		String path = "";
		User currentUser = null;
		if (session.getAttribute("userLogged") == null) {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			String name = auth.getName();
			currentUser = userService.findByEmail(name);
			session.setAttribute("userLogged", currentUser);
		} else {
			currentUser = (User) session.getAttribute("userLogged");
		}
		// plusieurs groupes
		if (currentUser.getNbGroup() > 1) {
			model.addAttribute("utilisateur", currentUser);
			path = "forum/list";
		} else {
			if (currentUser.onlyOneGroup()) {
				Group g = currentUser.getSingleGroup();
				path = "redirect:/forum/" + g.getSlug();
			}
		}
		return path;
	}

	@InitBinder
	protected void initBinder(WebDataBinder binder) throws Exception {
		DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
		df.setLenient(false);
		binder.registerCustomEditor(Date.class, new CustomDateEditor(df, true));

	}

	@RequestMapping(value = "/{nameForum}", method = RequestMethod.GET)
	public String viewForum(ServletRequest request,HttpSession session, Model model,
			@PathVariable String nameForum) throws UnsupportedEncodingException {
		User currentUser = null;
		request.setCharacterEncoding("UTF-8");
		if (session.getAttribute("userLogged") == null) {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			String name = auth.getName();
			currentUser = userService.findByEmail(name);
			session.setAttribute("userLogged", currentUser);
		} else {
			currentUser = (User) session.getAttribute("userLogged");
		}
		Group g = groupService.findBySlug(nameForum);
		session.setAttribute("groupeCurrent", g);
		List<SujetForum> lstSujets = sujetForumService.getAllSujets(g);
		model.addAttribute("sujets", lstSujets);
		model.addAttribute("groupe", g);
		model.addAttribute("nomForum",nameForum);
		model.addAttribute("utilisateur", currentUser);
		return "forum/viewForum";
	}

	@RequestMapping(value = "/{name}/ajoutSujet", method = RequestMethod.GET)
	public String addSujet(HttpSession session, Model model) {
		User currentUser = null;
		if (session.getAttribute("userLogged") == null) {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			String name = auth.getName();
			currentUser = userService.findByEmail(name);
		} else {
			currentUser = (User) session.getAttribute("userLogged");
		}
		// prevent error group not in session
		if (session.getAttribute("groupeCurrent") == null) {
			return "forum/list";
		}
		Group g = (Group) session.getAttribute("groupeCurrent");
		model.addAttribute("user", currentUser);
		model.addAttribute("groupe", g);
		model.addAttribute("sujet", new SujetForum(currentUser, g));
		return "forum/addSujet";
	}

	@RequestMapping(value = "/{name}/ajoutSujet", method = RequestMethod.POST)
	public String postSujet(@ModelAttribute("sujet") @Valid SujetForum sujet,
			BindingResult result, HttpSession session) {
		Group g = (Group) session.getAttribute("groupeCurrent");
		if (result.hasErrors()) {
			System.out.println("Errors are ::" + result.toString());
			return "forum/addSujet";
		} else {
			// pas d'erreur code ici
			sujet.setDateCreation(new Date());
			sujet.setDateLastResponse(sujet.getDateCreation());
			sujetForumService.add(sujet, result);
		}
		if (g == null)
			return "redirect:/forum/";
		return "redirect:/forum/" + g.getSlug();
	}

	@RequestMapping(value = "/{name}/{idSujet}", method = RequestMethod.GET)
	public String viewSujet(HttpSession session, Model model,
			@PathVariable("name") String nameForum,
			@PathVariable("idSujet") Integer id) throws SujetNotFoundException {
		User currentUser = null;
		if (session.getAttribute("userLogged") == null) {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			String name = auth.getName();
			currentUser = userService.findByEmail(name);
		} else {
			currentUser = (User) session.getAttribute("userLogged");
		}
		// System.out.println("sujet "+sujet);
		// System.out.println("forum "+nameForum);
		// System.out.println("sf "+sf);
		SujetForum sf = sujetForumService.findById(id);
		if (sf == null){
			throw new SujetNotFoundException();
		}
		Group g = (Group) session.getAttribute("groupeCurrent");
		List<ResponseForum> lstRep = reponseForumService.getListResponses(sf);
		model.addAttribute("sujet", sf);
		model.addAttribute("groupe", g);
		model.addAttribute("user", currentUser);
		model.addAttribute("reponses", lstRep);
		return "forum/viewSujet";
	}

	@RequestMapping(value = "/{name}/{idSujet}/edit", method = RequestMethod.GET)
	public String editSujet(HttpSession session, Model model,
			@PathVariable("name") String nameForum,
			@PathVariable("idSujet") Integer id) {
		User currentUser = null;
		if (session.getAttribute("userLogged") == null) {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			String name = auth.getName();
			currentUser = userService.findByEmail(name);
		} else {
			currentUser = (User) session.getAttribute("userLogged");
		}
		SujetForum sf = sujetForumService.findById(id);
		if (sf.getCreateur().getIdUser() == currentUser.getIdUser()) {
			Group g = sf.getForum();
			model.addAttribute("sujet", sf);
			model.addAttribute("groupe", g);
			model.addAttribute("user", currentUser);
			return "forum/editSujet";
		}
		return "redirect:/forum/" + sf.getForum().getSlug();
	}

	@RequestMapping(value = "/{name}/{idSujet}/edit", method = RequestMethod.POST)
	public String updateEditSujet(
			@ModelAttribute("sujet") @Valid SujetForum sujet,
			BindingResult result, HttpSession session) {
		Group g = groupService.findById(sujet.getForum().getIdGroup());
		if (result.hasErrors()) {
			System.out.println("Errors are ::" + result.toString());
			return "forum/editSujet";
		} else {
			// pas d'erreur code ici
			sujet.addTagEditSujet();
			sujetForumService.updateSujet(sujet);
		}
		return "redirect:/forum/" + g.getSlug();
	}

	@RequestMapping(value = "/{name}/editmsg/{idReponse}", method = RequestMethod.GET)
	public String editReponse(HttpSession session, Model model,
			@PathVariable("name") String nameForum,
			@PathVariable("idReponse") Integer id) {
		User currentUser = null;
		if (session.getAttribute("userLogged") == null) {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			String name = auth.getName();
			currentUser = userService.findByEmail(name);
		} else {
			currentUser = (User) session.getAttribute("userLogged");
		}
		ResponseForum r = reponseForumService.findById(id);
		if (r.getPostedBy().getIdUser() == currentUser.getIdUser()) {
			model.addAttribute("reponse", r);
			model.addAttribute("sujet", r.getSujet());
			model.addAttribute("user", currentUser);
			return "forum/editReponse";
		}
		return "redirect:/forum/" + r.getSujet().getForum().getSlug();
	}

	@RequestMapping(value = "/{name}/editmsg/{idReponse}", method = RequestMethod.POST)
	public String updateEditReponse(
			@ModelAttribute("reponse") @Valid ResponseForum reponse,
			BindingResult result, HttpSession session) {
		Group g = (Group) session.getAttribute("groupeCurrent");
		if (result.hasErrors()) {
			System.out.println("Errors are ::" + result.toString());
			return "forum/editReponse";
		} else {
			// pas d'erreur code ici
			reponse.addTagEditReponse();
			reponseForumService.updateSujet(reponse);
		}
		if (g == null)
			return "redirect:/forum/";
		return "redirect:/forum/" + g.getSlug();
	}

	@RequestMapping(value = "/{name}/ajoutReponse", method = RequestMethod.POST)
	public String addReponse(HttpSession session, HttpServletRequest request,
			Model model) {
		User currentUser = null;
		if (session.getAttribute("userLogged") == null) {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			String name = auth.getName();
			currentUser = userService.findByEmail(name);
		} else {
			currentUser = (User) session.getAttribute("userLogged");
		}
		int id = Integer.valueOf(request.getParameter("idSujet"));
		SujetForum s = sujetForumService.findById(id);
		// prevent add response to closed subject
		if (s.getisClose())
			return "redirect:/forum/" + s.getForum().getSlug();
		model.addAttribute("user", currentUser);
		model.addAttribute("sujet", s);
		model.addAttribute("rep", new ResponseForum(currentUser, s));
		return "forum/addReponse";
	}

	@RequestMapping(value = "/{name}/ajoutReponse/post", method = RequestMethod.POST)
	public String postReponse(@ModelAttribute("rep") @Valid ResponseForum rep,
			BindingResult result, HttpSession session) {
		if (result.hasErrors()) {
			System.out.println("Errors are ::" + result.toString());
			return "forum/addReponse";
		} else {
			// prevent add response to closed subject
			if (rep.getSujet().getisClose() == true)
				return "redirect:/forum/" + rep.getSujet().getForum().getSlug();
			rep.setDateLastModification(new Date());
			reponseForumService.add(rep, result);
		}
		return "redirect:/forum/" + rep.getSujet().getForum().getSlug();
	}

	@RequestMapping(value = "/{name}/{idSujet}/lock", method = RequestMethod.GET)
	public String lockSujet(HttpSession session, Model model,
			@PathVariable("name") String nameForum,
			@PathVariable("idSujet") Integer id) {
		SujetForum sf = sujetForumService.findById(id);
		sf.lock();
		sujetForumService.updateSujet(sf);
		return "redirect:/forum/" + nameForum;
	}

	@RequestMapping(value = "/{name}/{idSujet}/unlock", method = RequestMethod.GET)
	public String unlockSujet(HttpSession session, Model model,
			@PathVariable("name") String nameForum,
			@PathVariable("idSujet") Integer id) {
		SujetForum sf = sujetForumService.findById(id);
		sf.unlock();
		sujetForumService.updateSujet(sf);
		return "redirect:/forum/" + nameForum;
	}

	@RequestMapping(value = "/{name}/{idSujet}/delete", method = RequestMethod.GET)
	public String deleteSujet(HttpSession session, Model model,
			@PathVariable("name") String nameForum,
			@PathVariable("idSujet") Integer id) {
		SujetForum sf = sujetForumService.findById(id);
		sujetForumService.deleteSujet(sf);
		return "redirect:/forum/" + nameForum;
	}

	@RequestMapping(value = "/{name}/{idSujet}/delete/{idReponse}", method = RequestMethod.GET)
	public String deleteReponse(HttpSession session, Model model,
			@PathVariable("name") String nameForum,
			@PathVariable("idSujet") Integer id,
			@PathVariable("idReponse") Integer idReponse) {
		ResponseForum r = reponseForumService.findById(idReponse);
		SujetForum sf = sujetForumService.findById(id);
		sf.deleteReponse();
		sujetForumService.updateSujet(sf);
		reponseForumService.deleteReponse(r);
		return "redirect:/forum/" + nameForum;
	}

	@RequestMapping(value = "/{name}/{idSujet}/moderer", method = RequestMethod.GET)
	public String modererSujet(HttpSession session, Model model,
			@PathVariable("name") String nameForum,
			@PathVariable("idSujet") Integer id) {
		User currentUser = null;
		if (session.getAttribute("userLogged") == null) {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			String name = auth.getName();
			currentUser = userService.findByEmail(name);
		} else {
			currentUser = (User) session.getAttribute("userLogged");
		}
		SujetForum sf = sujetForumService.findById(id);
		if (currentUser.isAdmin()) {
			Group g = sf.getForum();
			model.addAttribute("sujet", sf);
			model.addAttribute("groupe", g);
			model.addAttribute("user", currentUser);
			return "forum/editSujet";
		}
		return "redirect:/forum/" + sf.getForum().getSlug();
	}

	@RequestMapping(value = "/{name}/{idSujet}/moderer", method = RequestMethod.POST)
	public String updateModererSujet(
			@ModelAttribute("sujet") @Valid SujetForum sujet,
			BindingResult result, HttpSession session) {
		Group g = groupService.findById(sujet.getForum().getIdGroup());
		System.out.println("g " + g);
		if (result.hasErrors()) {
			System.out.println("Errors are ::" + result.toString());
			return "forum/editSujet";
		} else {
			// pas d'erreur code ici
			System.out.println("sujet " + sujet);
			sujet.addTagModereSujet();
			sujetForumService.updateSujet(sujet);
		}
		return "redirect:/forum/" + g.getSlug();
	}

	@RequestMapping(value = "/{name}/moderermsg/{idReponse}", method = RequestMethod.GET)
	public String modererReponse(HttpSession session, Model model,
			@PathVariable("name") String nameForum,
			@PathVariable("idReponse") Integer id) {
		User currentUser = null;
		if (session.getAttribute("userLogged") == null) {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			String name = auth.getName();
			currentUser = userService.findByEmail(name);
		} else {
			currentUser = (User) session.getAttribute("userLogged");
		}
		ResponseForum r = reponseForumService.findById(id);
		if (currentUser.isAdmin()) {
			model.addAttribute("reponse", r);
			model.addAttribute("sujet", r.getSujet());
			model.addAttribute("user", currentUser);
			return "forum/editReponse";
		}
		return "redirect:/forum/" + r.getSujet().getForum().getSlug();
	}

	@RequestMapping(value = "/{name}/moderermsg/{idReponse}", method = RequestMethod.POST)
	public String updateModererReponse(
			@ModelAttribute("reponse") @Valid ResponseForum reponse,
			BindingResult result, HttpSession session,
			@PathVariable("idReponse") Integer id) {
		ResponseForum r = reponseForumService.findById(id);
		if (result.hasErrors()) {
			System.out.println("Errors are ::" + result.toString());
			return "forum/editReponse";
		} else {
			// pas d'erreur code ici
			reponse.addTagModereReponse();
			reponseForumService.updateSujet(reponse);
		}
		return "redirect:/forum/" + r.getSujet().getForum().getSlug();
	}
	
	@ExceptionHandler(SujetNotFoundException.class)
	public ModelAndView handleCustomException(SujetNotFoundException ex) {

		ModelAndView model = new ModelAndView("errors/custom_error");
		model.addObject("exception", ex);
		return model;
 
	}
}
